package net.wicp.tams.common.binlog.self.bean;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.collections.CollectionUtils;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import net.wicp.tams.common.apiext.JdbcUtil;
import net.wicp.tams.common.apiext.StringUtil;
import net.wicp.tams.common.constant.StrPattern;

/**
 * 主机
 * 
 * @author andy.zhou
 *
 */
@Data
@Builder
public class Host implements Comparable<Host> {
	public final static String preVar = "zorro-host";

	private String hostName;
	private String hostIp;
	private int port;
	private final String charsetName = "UTF-8";

	private String user;
	private String pwd;
	private String defaultDb;

	//
	private String dbPattern;
	private String tbPattern;

	@Getter(value = AccessLevel.PRIVATE)
	private final Map<String, List<String>> colsMap;// key为 db.tb value为：col逗号分隔

	@Getter(value = AccessLevel.PRIVATE)
	private final Map<Long, TableMapBean> tbmaps = new HashMap<>();// TableMap事件产生的对象

	public void addTableMapBean(TableMapBean tableMapBean) {
		if (tableMapBean == null) {
			return;
		}
		tbmaps.put(tableMapBean.getTableId(), tableMapBean);
	}

	public boolean checkTable(String schemaName, String tableName) {
		if (StringUtil.isNotNull(dbPattern)) {
			boolean ret = StrPattern.checkStrFormat(dbPattern, schemaName);
			if (!ret) {
				return false;
			}
		}
		if (StringUtil.isNotNull(tbPattern)) {
			boolean ret = StrPattern.checkStrFormat(tbPattern, tableName);
			if (!ret) {
				return false;
			}
		}
		return true;
	}

	public TableMapBean findTableMapBean(Long tabId) {
		return tbmaps.get(tabId);
	}

	public boolean containsTabId(Long tabId) {
		return tbmaps.containsKey(tabId);
	}

	public Host() {
		this.colsMap = new HashMap<>();
	}

	public Host(String hostName, String hostIp, int port, String user, String pwd, String defaultDb, String dbPattern,
			String tbPattern, Map<String, List<String>> colsMap) {
		super();
		this.hostName = hostName;
		this.hostIp = hostIp;
		this.port = port;
		this.user = user;
		this.pwd = pwd;
		this.defaultDb = defaultDb;
		this.colsMap = colsMap;
		this.dbPattern = dbPattern;
		this.tbPattern = tbPattern;
	}

	@Override
	public boolean equals(Object obj) {
		Host temp = (Host) obj;
		if (this.hostIp.equals(temp.getHostIp()) && this.port == temp.getPort()) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public int hashCode() {
		return hostIp.hashCode() * 37 + port;
	}

	@Override
	public int compareTo(Host o) {
		String[] ips1 = this.hostIp.split(".");
		String[] ips2 = o.getHostIp().split(".");
		for (int i = 0; i < 4; i++) {
			int si1 = Integer.parseInt(ips1[i]);
			int si2 = Integer.parseInt(ips2[i]);
			if (si1 != si2) {
				return si1 - si2;
			}
		}
		return this.port - o.getPort();
	}

	public List<String> getCols(String schemaName, String tableName) {
		String key = findKey(schemaName, tableName);
		if (!colsMap.containsKey(key)) {
			List<String> ret = new ArrayList<>();
			String url = String.format("jdbc:mysql://%s:%s?autoReconnect=true&useUnicode=true&characterEncoding=utf-8",
					this.hostIp, this.port);

			java.sql.Connection conn = JdbcUtil.getConnection("com.mysql.jdbc.Driver", url, this.user, this.pwd);
			PreparedStatement prep;
			try {
				prep = conn.prepareStatement(
						"select   column_name   from  information_schema.columns  where  table_schema=? and table_name=?");
				JdbcUtil.setPreParam(prep, schemaName, tableName);
				ResultSet rs = prep.executeQuery();
				while (rs.next()) {
					ret.add(rs.getString(1));
				}
				if (CollectionUtils.isNotEmpty(ret)) {
					colsMap.put(key, ret);
				}
				rs.close();
			} catch (SQLException e) {
			} finally {
				try {
					conn.close();
				} catch (SQLException e) {
				}
			}
		}
		return colsMap.get(key);
	}

	public void addCols(Properties cols) {
		if (cols == null || cols.size() == 0) {
			return;
		}
		for (Object obj : cols.keySet()) {
			String key = String.valueOf(obj);
			String[] input = key.split("\\.");
			String keytrue = findKey(input[0], input[1]);
			String val = cols.getProperty(key);
			colsMap.put(keytrue, Arrays.asList(val.split(",")));
		}
	}

	public void delCols(String schemaName, String tableName) {
		String key = findKey(schemaName, tableName);
		colsMap.remove(key);
	}

	private String findKey(String schemaName, String tableName) {
		String key_db = schemaName;
		if (StrPattern.db_split.checkStrFormat(schemaName)) {
			int lastint = schemaName.lastIndexOf("_");
			key_db = schemaName.substring(0, lastint + 1) + "00";
		}

		String key_tb = tableName;
		if (StrPattern.tb_split.checkStrFormat(tableName)) {
			int lastint = tableName.lastIndexOf("_");
			key_tb = tableName.substring(0, lastint + 1) + "0000";
		}
		String key = String.format("%s.%s", key_db, key_tb);
		return key;
	}

}
